我们都听说过一个流行词——“数据科学”。我们大多数人都对“它是什么?我可以成为数据分析师或数据科学家吗?我需要什么技能?并不是很了解。例如:我想开始一个数据科学项目,但我却不知道如何着手进行。
我们大多数人都是通过一些在线课程了解了这个领域。我们对课程中布置的作业和项目感到游刃有余。但是,当开始分析全新或未知的数据集时,我们会迷失方向。为了在分析我们遇到的任何数据集和问题时,我们需要通过不断的练习。我觉得最好的方式之一就是在项目中进行学习。所以每个人都需要开始自己的第一个项目。因此,我准备写一个专栏,带大家一起完成数据科学项目,感兴趣的朋友可以一起交流学习。本专栏是一个以实战为主的专栏。

随着产品和服务在线消费的增加,消费者面临着收件箱中大量垃圾邮件的巨大问题,这些垃圾邮件要么是基于促销的,要么是欺诈性的。由于这个原因,一些非常重要的消息/电子邮件被当做垃圾短信处理了。在本文中,我们将创建一个 垃圾短信/邮件检测模型,该模型将使用朴素贝叶斯和自然语言处理(NLP) 来确定是否为垃圾短信/邮件。
在这里我使用的是colab内置环境,完整代码文末获取。
额外的所需包如下,大家自行安装
nltk
streamlit
pickle
我们将使用kaggle提供的数据集:数据集
该数据集 包含一组带有标记的短信文本,这些消息被归类为正常短信和垃圾短信。 每行包含一条消息。每行由两列组成:v1 带有标签,(spam 或 ham),v2 是文本内容。
df=pd.read_csv('/content/spam/spam.csv',encoding='latin-1')#这里encoding需要指定为latin-1
# 查看一下数据基本情况
df.head()
| v1 | v2 | Unnamed: 2 | Unnamed: 3 | Unnamed: 4 | |
|---|---|---|---|---|---|
| 0 | ham | Go until jurong point, crazy.. Available only ... | NaN | NaN | NaN |
| 1 | ham | Ok lar... Joking wif u oni... | NaN | NaN | NaN |
| 2 | spam | Free entry in 2 a wkly comp to win FA Cup fina... | NaN | NaN | NaN |
| 3 | ham | U dun say so early hor... U c already then say... | NaN | NaN | NaN |
| 4 | ham | Nah I don't think he goes to usf, he lives aro... | NaN | NaN | NaN |
该数据包含一组带有标记的短信数据,其中:
- v1表示短信标签,ham表示正常信息,spam表示垃圾信息
- v2是短信的内容
#去除不需要的列
df=df.iloc[:,:2]
#重命名列
df=df.rename(columns={"v1":"label","v2":"message"})
df.head()
| label | message | |
|---|---|---|
| 0 | ham | Go until jurong point, crazy.. Available only ... |
| 1 | ham | Ok lar... Joking wif u oni... |
| 2 | spam | Free entry in 2 a wkly comp to win FA Cup fina... |
| 3 | ham | U dun say so early hor... U c already then say... |
| 4 | ham | Nah I don't think he goes to usf, he lives aro... |
# 将lable进行one-hot编码,其中0:ham,1:spam
from sklearn.preprocessing import LabelEncoder
encoder = LabelEncoder()
df['label']=encoder.fit_transform(df['label'])
df['label'].value_counts()
0 4825
1 747
Name: label, dtype: int64
可以看出一共有747个垃圾短信
# 查看缺失值
df.isnull().sum()
# 数据没有缺失值
label 0
message 0
dtype: int64
通过可视化分析来更好的理解数据
import matplotlib.pyplot as plt
plt.style.use('ggplot')
plt.figure(figsize=(9,4))
plt.subplot(1,2,1)
plt.pie(df['label'].value_counts(),labels=['not spam','spam'],autopct="%0.2f")
plt.subplot(1,2,2)
sns.barplot(x=df['label'].value_counts().index,y=df['label'].value_counts(),data=df)
plt.show()

在特征工程部分,我简单创建了一些单独的特征来提取信息
#1.字符数
df['char']=df['message'].apply(len)
nltk.download('punkt')
[nltk_data] Downloading package punkt to /root/nltk_data...
[nltk_data] Unzipping tokenizers/punkt.zip.
True
#2.单词数,这里我们首先要对其进行分词处理,使用nltk
#分词处理
df['words']=df['message'].apply(lambda x: len(nltk.word_tokenize(x)))
# 3.句子数
df['sen']=df['message'].apply(lambda x: len(nltk.sent_tokenize(x)))
df.head()
| label | message | char | words | sen | |
|---|---|---|---|---|---|
| 0 | 0 | Go until jurong point, crazy.. Available only ... | 111 | 24 | 2 |
| 1 | 0 | Ok lar... Joking wif u oni... | 29 | 8 | 2 |
| 2 | 1 | Free entry in 2 a wkly comp to win FA Cup fina... | 155 | 37 | 2 |
| 3 | 0 | U dun say so early hor... U c already then say... | 49 | 13 | 1 |
| 4 | 0 | Nah I don't think he goes to usf, he lives aro... | 61 | 15 | 1 |
描述性统计
# 描述性统计
df.describe()
| index | label | char | words | sen |
|---|---|---|---|---|
| count | 5572.0 | 5572.0 | 5572.0 | 5572.0 |
| mean | 0.13406317300789664 | 80.11880832735105 | 18.69562096195262 | 1.9707465900933239 |
| std | 0.34075075489776974 | 59.6908407765033 | 13.742586801744975 | 1.4177777134026657 |
| min | 0.0 | 2.0 | 1.0 | 1.0 |
| 25% | 0.0 | 36.0 | 9.0 | 1.0 |
| 50% | 0.0 | 61.0 | 15.0 | 1.0 |
| 75% | 0.0 | 121.0 | 27.0 | 2.0 |
| max | 1.0 | 910.0 | 220.0 | 28.0 |
下面我们通过可视化比较一下不同短信在这些数字特征上的分布情况
# 字符数比较
plt.figure(figsize=(12,6))
sns.histplot(df[df['label']==0]['char'],color='red')#正常短信
sns.histplot(df[df['label']==1]['char'],color = 'blue')#垃圾短信
<matplotlib.axes._subplots.AxesSubplot at 0x7fce63763dd0>

# 比较
plt.figure(figsize=(12,6))
sns.histplot(df[df['label']==0]['words'],color='red')#正常短信
sns.histplot(df[df['label']==1]['words'],color = 'blue')#垃圾短信
<matplotlib.axes._subplots.AxesSubplot at 0x7fce63f4bed0>

sns.pairplot(df,hue='label')

#删除数据集中存在的一些异常值
i=df[df['char']>500].index
df.drop(i,axis=0,inplace=True)
df=df.reset_index()
df.drop("index",inplace=True,axis=1)
#相关系数矩阵
sns.heatmap(df.corr(),annot=True)
<matplotlib.axes._subplots.AxesSubplot at 0x7fce606d0250>

我们这里看到存在多重共线性,因此,我们不使用所有的列,在这里选择与label相关性最强的char
对于英文文本数据,我们常用的数据预处理方式如下
下面我们来看看如何实现这些步骤
nltk.download('stopwords')
[nltk_data] Downloading package stopwords to /root/nltk_data...
[nltk_data] Unzipping corpora/stopwords.zip.
True
# 首先导入需要使用到的包
from nltk.corpus import stopwords
from nltk.stem import PorterStemmer
from wordcloud import WordCloud
import string,time
# 标点符号
string.punctuation
'!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
# 停用词
stopwords.words('english')
下面使用正则表达式来处理这些数据。
def remove_website_links(text):
no_website_links = text.replace(r"http\S+", "")#去除网络连接
return no_website_links
def remove_numbers(text):
removed_numbers = text.replace(r'\d+','')#去除数字
return removed_numbers
def remove_emails(text):
no_emails = text.replace(r"\S*@\S*\s?",'')#去除邮件
return no_emails
df['message'] = df['message'].apply(remove_website_links)
df['message'] = df['message'].apply(remove_numbers)
df['message'] = df['message'].apply(remove_emails)
df.head()
| label | message | char | words | sen | |
|---|---|---|---|---|---|
| 0 | 0 | Go until jurong point, crazy.. Available only ... | 111 | 24 | 2 |
| 1 | 0 | Ok lar... Joking wif u oni... | 29 | 8 | 2 |
| 2 | 1 | Free entry in 2 a wkly comp to win FA Cup fina... | 155 | 37 | 2 |
| 3 | 0 | U dun say so early hor... U c already then say... | 49 | 13 | 1 |
| 4 | 0 | Nah I don't think he goes to usf, he lives aro... | 61 | 15 | 1 |
def message_transform(text):
text = text.lower()#转换为小写
text = nltk.word_tokenize(text)#分词处理
# 去除停用词和标点
y = []#创建一个空列表
for word in text:
stopwords_punc = stopwords.words('english')+list(string.punctuation)#存放停用词和标点
if word.isalnum()==True and word not in stopwords_punc:
y.append(word)
# 词根变换
message=y[:]
y.clear()
for i in message:
ps=PorterStemmer()
y.append(ps.stem(i))
return " ".join(y)#返回字符串形式
df['message'] = df['message'].apply(message_transform)
df['num_words_transform']=df['message'].apply(lambda x: len(str(x).split()))
df.head()
| label | message | char | words | sen | |
|---|---|---|---|---|---|
| 0 | 0 | Go until jurong point, crazy.. Available only ... | 111 | 24 | 2 |
| 1 | 0 | Ok lar... Joking wif u oni... | 29 | 8 | 2 |
| 2 | 1 | Free entry in 2 a wkly comp to win FA Cup fina... | 155 | 37 | 2 |
| 3 | 0 | U dun say so early hor... U c already then say... | 49 | 13 | 1 |
| 4 | 0 | Nah I don't think he goes to usf, he lives aro... | 61 | 15 | 1 |
#绘制信息中出现最多的词的词云
from wordcloud import WordCloud
#首先,创建一个object
wc=WordCloud(width=500,height=500,min_font_size=10,background_color='white')
# 垃圾信息的词云
spam_wc=wc.generate(df[df['label']==1]['message'].str.cat(sep=""))
plt.figure(figsize=(18,12))
plt.imshow(spam_wc)
<matplotlib.image.AxesImage at 0x7fce5d938710>

可以看出,这些垃圾邮件出现频次最多的单词是:free、call等这种具有诱导性的信息
# 正常信息的词云
ham_wc = wc.generate(df[df['label']==0]['message'].str.cat(sep=''))
plt.figure(figsize=(18,12))
plt.imshow(ham_wc)
<matplotlib.image.AxesImage at 0x7fce607af190>

可以看出正常信息出现频次较多的单词为u、go、got、want等一些传达信息的单词
为了简化词云图的信息,我们现在分别统计垃圾短信和正常短信频次top30的单词
垃圾短信:
# 统计词频
spam_corpus=[]
for i in df[df['label']==1]['message'].tolist():
for word in i.split():
spam_corpus.append(word)
from collections import Counter
Counter(spam_corpus)#记数
Counter(spam_corpus).most_common(30)#取最多的30个单词
plt.figure(figsize=(10,7))
sns.barplot(y=pd.DataFrame(Counter(spam_corpus).most_common(30))[0],x=pd.DataFrame(Counter(spam_corpus).most_common(30))[1])
plt.xticks()
plt.xlabel("Frequnecy")
plt.ylabel("Spam Words")
plt.show()

正常短信
ham_corpus=[]
for i in df[df['label']==0]['message'].tolist():
for word in i.split():
ham_corpus.append(word)
from collections import Counter
plt.figure(figsize=(10,7))
sns.barplot(y=pd.DataFrame(Counter(ham_corpus).most_common(30))[0],x=pd.DataFrame(Counter(ham_corpus).most_common(30))[1])
plt.xticks()
plt.xlabel("Frequnecy")
plt.ylabel("Ham Words")
plt.show()

下面进一步分析垃圾短信和非垃圾短信的单词和字符数分布情况
# 字符数
fig,(ax1,ax2)=plt.subplots(1,2,figsize=(15,6))
text_len=df[df['label']==1]['text'].str.len()
ax1.hist(text_len,color='green')
ax1.set_title('Original text')
text_len=df[df['label']==0]['text'].str.len()
ax2.hist(text_len,color='red')
ax2.set_title('Fake text')
fig.suptitle('Characters in texts')
plt.show()

#单词数
fig,(ax1,ax2)=plt.subplots(1,2,figsize=(15,6))
text_len=df[df['label']==1]['num_words_transform']
ax1.hist(text_len,color='red')
ax1.set_title('Original text')
text_len=df[df['label']==0]['num_words_transform']
ax2.hist(text_len,color='green')
ax2.set_title('Fake text')
fig.suptitle('Words in texts')
plt.show()

总结
经过上面分析,我们可以得出结论,垃圾短信文本与非垃圾短信文本相比具有更多的单词和字符。
- 垃圾短信中包含的平均字符数约为 90 个字符
- 垃圾短信中包含的平均字数约为 15 个字
根据历史经验,在文本数据上朴素贝叶斯算法效果很好,因此我们将使用它,但在此过程中还将它与不同的算法进行比较。
在统计学中,朴素贝叶斯分类器是一系列简单的“概率分类器”,它们基于应用贝叶斯定理和特征之间的(朴素)条件独立假设。它们是最简单的贝叶斯网络模型之一,但与核密度估计相结合,它们可以达到更高的准确度水平。

首先,我们这里的输入数据是文本数据,不能够直接建立模型。因此,我们必须将这些文本数据进行特征提取。比较常用的几种方法:
因为是实战训练,在这里不具体展开的几种方法的原理,在这里我选择TF-IDF。

我也试了一下Word embedding,结合一些深度学习的方法,精度能够有所提高,感兴趣的小伙伴可以自己尝试一下,基本步骤类似。下面我们首先建立贝叶斯模型。
from sklearn.feature_extraction.text import TfidfVectorizer
tfidf = TfidfVectorizer(max_features=3000)
X = tfidf.fit_transform(df['message']).toarray()
y = df['label'].values
array([0, 0, 1, ..., 0, 0, 0])
from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.2,random_state=2)#训练集测试集划分
from sklearn.naive_bayes import GaussianNB,MultinomialNB,BernoulliNB
from sklearn.metrics import accuracy_score,confusion_matrix,precision_score
这里我们比较三种不同的贝叶斯模型的各个评估指标结果
#GaussianNB
gnb = GaussianNB()
gnb.fit(X_train,y_train)
y_pred1 = gnb.predict(X_test)
print("Accuracy Score -",accuracy_score(y_test,y_pred1))
print("Precision Score -",precision_score(y_test,y_pred1))
print(confusion_matrix(y_test,y_pred1))
Accuracy Score - 0.8456014362657092
Precision Score - 0.47038327526132406
[[807 152]
[ 20 135]]
#MultinomialNB
mnb = MultinomialNB()
mnb.fit(X_train,y_train)
y_pred2 = mnb.predict(X_test)
print("Accuracy Score -",accuracy_score(y_test,y_pred2))
print("Precision Score -",precision_score(y_test,y_pred2))
print(confusion_matrix(y_test,y_pred2))
Accuracy Score - 0.9793536804308797
Precision Score - 0.9925373134328358
[[958 1]
[ 22 133]]
#Bernuli
bnb = BernoulliNB()
bnb.fit(X_train,y_train)
y_pred3 = bnb.predict(X_test)
print("Accuracy Score -",accuracy_score(y_test,y_pred3))
print("Precision Score -",precision_score(y_test,y_pred3))
print(confusion_matrix(y_test,y_pred3))
Accuracy Score - 0.9829443447037702
Precision Score - 1.0
[[959 0]
[ 19 136]]
从上述结果来看,我选择了BNB来建模
下面我们继续比较其他几种常见的分类模型的效果
#导入基本库
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.naive_bayes import MultinomialNB
from sklearn.tree import DecisionTreeClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import AdaBoostClassifier
from sklearn.ensemble import BaggingClassifier
from sklearn.ensemble import ExtraTreesClassifier
from sklearn.ensemble import GradientBoostingClassifier
from xgboost import XGBClassifier
from sklearn.metrics import precision_score, recall_score, plot_confusion_matrix, classification_report, accuracy_score, f1_score
from sklearn.model_selection import cross_val_score
# 构建多个分类器
classifiers={"svc":SVC(kernel='sigmoid', gamma=1.0),
"knc": KNeighborsClassifier(),
"bnb" : BernoulliNB(),
"dtc" : DecisionTreeClassifier(max_depth=5),
"lr" : LogisticRegression(solver='liblinear', penalty='l1'),
"rfc" : RandomForestClassifier(n_estimators=50, random_state=2),
"adb" : AdaBoostClassifier(n_estimators=50, random_state=2),
"xgb" : XGBClassifier(n_estimators=50,random_state=2),
"gbc" : GradientBoostingClassifier(n_estimators=50,random_state=2)
}
# 训练分类器函数
def train_classifier(clf,X_train,y_train,X_test,y_test):
clf.fit(X_train,y_train)
y_pred = clf.predict(X_test)
accuracy = accuracy_score(y_test,y_pred)
precision = precision_score(y_test,y_pred)
train_accuracy = clf.score(X_train,y_train)
return accuracy,precision,train_accuracy
# 得到各个模型的评估结果
accuracy_scores = []
precision_scores = []
train_accuracy_score=[]
for name,clf in classifiers.items():
current_accuracy,current_precision,current_train_score = train_classifier(clf, X_train,y_train,X_test,y_test)
print("For ",name)
print("Accuracy - ",current_accuracy)
print("Precision - ",current_precision)
accuracy_scores.append(current_accuracy)
precision_scores.append(current_precision)
train_accuracy_score.append(current_train_score)
print()
For svc
Accuracy - 0.9802513464991023
Precision - 0.9784172661870504
For knc
Accuracy - 0.9093357271095153
Precision - 1.0
For bnb
Accuracy - 0.9829443447037702
Precision - 1.0
For dtc
Accuracy - 0.9299820466786356
Precision - 0.8811881188118812
For lr
Accuracy - 0.9622980251346499
Precision - 0.959349593495935
For rfc
Accuracy - 0.9721723518850988
Precision - 0.9920634920634921
For adb
Accuracy - 0.966786355475763
Precision - 0.9338235294117647
For xgb
Accuracy - 0.9443447037701975
Precision - 0.9514563106796117
For gbc
Accuracy - 0.9542190305206463
Precision - 0.9642857142857143
为了方便对比,将上述结果存放到dataframe中
df1=pd.DataFrame({'Algorithm':classifiers.keys(),'Precision':precision_scores,
'Test Accuracy':accuracy_scores}).round(3)
df2=df1.sort_values(['Precision','Test Accuracy'],ascending=False)#排序
df2
| Algorithm | Precision | Test Accuracy | |
|---|---|---|---|
| 2 | bnb | 1.000 | 0.983 |
| 1 | knc | 1.000 | 0.909 |
| 5 | rfc | 0.992 | 0.972 |
| 0 | svc | 0.978 | 0.980 |
| 8 | gbc | 0.964 | 0.954 |
| 4 | lr | 0.959 | 0.962 |
| 7 | xgb | 0.951 | 0.944 |
| 6 | adb | 0.934 | 0.967 |
| 3 | dtc | 0.881 | 0.930 |
通过对比,选择BNB模型,模型的precision为100%,accuracy为98.3%
import pickle
pickle.dump(tfidf,open('vectorizer.pkl','wb'))
pickle.dump(mnb,open('model.pkl','wb'))
然后打开 IDE 并创建自己的虚拟环境。使用 pip 或 conda 安装所需的所有包。我们将使用 streamlit 构建我们的网站。
设置完成后,创建app.py文件
import streamlit as st
import pickle
import string
from nltk.corpus import stopwords
import nltk
from nltk.stem.porter import PorterStemmer
ps = PorterStemmer()
def transform_text(text):
text = text.lower()
text = nltk.word_tokenize(text)
y = []
for i in text:
if i.isalnum():
y.append(i)
text = y[:]
y.clear()
for i in text:
if i not in stopwords.words('english') and i not in string.punctuation:
y.append(i)
text = y[:]
y.clear()
for i in text:
y.append(ps.stem(i))
return " ".join(y)
tfidf = pickle.load(open('vectorizer.pkl','rb'))
model = pickle.load(open('model.pkl','rb'))
st.title("垃圾短信/邮件分类器")
input_sms = st.text_area("输入你要检测的内容")
if st.button('Predict'):
# 1. preprocess
transformed_sms = transform_text(input_sms)
# 2. vectorize
vector_input = tfidf.transform([transformed_sms])
# 3. predict
result = model.predict(vector_input)[0]
# 4. Display
if result == 1:
st.header("垃圾短信!")
else:
st.header("正常短信~")
然后在本地运行
streamlit run app.py
然后就能到达下面这个界面了,将短信或者邮件输入点击预测就可以了

篇幅有限,完整代码可以在我的github上面查看,欢迎大家star,fork。
github地址:完整代码
如果访问不了github的可以私信我获取源码。
对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl
如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此
我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r
刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr
我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘
我已经像这样安装了一个新的Rails项目:$railsnewsite它执行并到达:bundleinstall但是当它似乎尝试安装依赖项时我得到了这个错误Gem::Ext::BuildError:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcheckingforlibkern/OSAtomic.h...yescreatingMakefilemake"DESTDIR="cleanmake"DESTDIR="
我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R
有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳